home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
PROGNG_C
/
TURBOCU1.LZH
/
XC3.ARC
/
XC3.C
next >
Wrap
Text File
|
1987-07-14
|
44KB
|
1,520 lines
/********************************************************************/
/* */
/* XC - A 'C' Xref Utility */
/* */
/* Version 1.0 January, 1982 */
/* */
/* Copyright (c) 1982 by Philip N. Hisley */
/* */
/* Philip N. Hisley */
/* 548H Jamestown Court */
/* Edgewood, Maryland 21040 */
/* (301) 679-4606 */
/* */
/* Released for non-commercial distribution only */
/* */
/* Converted to IBM/PC CI/C86 by David N. Smith, May/June 1983 */
/* with enhancements and Lattice compiler support in December 1983.*/
/* */
/* David N. Smith */
/* 44 Ole Musket Lane */
/* Danbury, CT 06810 */
/* (203) 748-5934 */
/* CompuServe: 73145,153 */
/* */
/* Changes Copyright (c) 1983 by David N. Smith */
/* Permission granted to copy for non-commercial purporses. */
/* */
/* PC Enhancements include: */
/* */
/* 1) Nested #INCLUDE statements */
/* 2) Single spaced cross-reference list */
/* 3) Removal of tabbing on output device */
/* (Since many printers don't support it) */
/* 4) #INCLUDE statements with both "--" and <--> */
/* syntax and with a full fileid in the quotes. */
/* 5) Multiple input filenames on command line. */
/* */
/* */
/* Minor additions by John Beamish, June 1984 */
/* */
/* John Beamish */
/* Box 340, Station T */
/* Toronto, Ontario */
/* M6B 4A3 */
/* (416) 782-1770 */
/* */
/* Changes Copyright (c) 1984 by John Beamish. */
/* Permission granted to copy for non-commercial purposes. */
/* */
/* 1. Added reserved words ENUM and VOID. */
/* 2. Variable names extended to 31 characters. */
/* 3. Tab option on command line. Tabs are expanded to number */
/* of spaces specified in value with -t flag. Default is 4. */
/* 4. Cross-reference prints a blank line when the first */
/* character changes. */
/* 5. Command line errors reported in a more descriptive fashion. */
/* 6. Listing "tidied-up" and some comments added. */
/* */
/* Converted to TURBOC (COMPACT MODEL) by */
/* */
/* Dean Limbaugh */
/* 6329 NW 28 Terrace */
/* Gainesville, Fl, 32606 */
/* CIS 72765,1162 */
/* */
/* Changes Copyright (c) 1987 by Dean Limbaugh */
/* Permission granted to copy for non-commercial purposes. */
/* */
/* 1. Added reserved words ASM, CDECL, CONST, FAR, INTERRUPT, */
/* NEAR, PASCAL, VOLATILE. */
/* 2. Added s & l options to -i. */
/* 3. Added -f, -p, -s, -q options. */
/* 4. Changed input to fix look ahead problem. (If identifier */
/* was last token on line, XREF would show it on the next line)*/
/* 5. Changed output to fix look ahead problem. (would print an */
/* extra blank line at EOF) */
/* 6. Changed include file processing to scan whole card. */
/* 7. Changed how hash table is handled to remove restriction on */
/* number of identifiers allowed. Now limited only by available*/
/* memory. */
/* 8. Changed title line to center file name and adjust to line */
/* width and changed XREF output to print the maximum number */
/* of references that would fit on a line. */
/* 9. Many other small changes. */
/* */
/* Lookahead problem still exists in printing reference table. */
/* That is, the program does not look to see if there are any */
/* references left to print when the current line becomes full */
/* so that if there are exactly as many references for an */
/* identifier as will fit on a line, an extra blank line will be */
/* printed. */
/* */
/* A good way to see how this program works is to use it on itself.*/
/* For example: */
/* */
/* xc xc.c -i > prn */
/* */
/* will run the program on itself, include the #include files */
/* and direct the output to the printer. */
/* */
/* Uploaded to PCanada by John Beamish (PC1048). */
/* */
/* */
/* Abstract: */
/* */
/* 'XC' is a cross-reference utility for 'C' programs. */
/* It has the ability to handle nested include files */
/* to a depth of 8 levels and properly processes nested */
/* comments as supported by BDS C. Option flags support */
/* the following features: */
/* */
/* - Routing of list output to disk */
/* - Cross-referencing of reserved words */
/* - Processing of nested include files */
/* - Generation of listing only */
/* */
/* Usage: xc <filename> <flag(s)> */
/* */
/* Flags: */
/* -i <s|l> = Enable file inclusion */
/* s = system include files */
/* l = local include files */
/* -l = Generate listing only */
/* -r = Cross-ref reserved words */
/* -o <filename> = Write output to named file */
/* -w <width> = No of output columns */
/* -t <number> = Number of spaces to expand each tab */
/* -f <filename> = File containing a list of file names */
/* -p <pathname> = Search path for include files */
/* -s = Print hashing stats */
/* -q = Don't print dots */
/* */
/* Note that flags -o -w -t -f -p must be immediately followed */
/* by the value for the flag. */
/* */
/********************************************************************/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <process.h>
#include <stdlib.h>
#if !defined(TRUE)
#define TRUE 1
#define FALSE 0
#endif
#define LINES_PER_PAGE 60 /* printed lines per page */
#define MAX_COL 78 /* def max col nmbr for list line */
#define MIN_COL 30 /* minimum value for -w option */
#define MIN_TAB 2 /* minimum value for -t option */
#define MAX_TAB 10 /* maximum value for -t option */
#define MAX_REF 5 /* maximum refs per ref-block */
#define MAX_LEN 65 /* maximum identifier length */
#define MAX_WRD 749 /* maximum number of identifiers */
#define MAX_ALPHA 53 /* maximum alpha chain heads */
#define ERROR -1 /* error flag */
#define FF 0x0C /* formfeed */
#define TAB 4 /* default value for -t option */
#define START_COLUMN 11 /* column of list line for source */
typedef struct RfBlk
{
int RefItem[MAX_REF];
int RefCnt;
struct RfBlk *Next;
} RfBlk;
typedef struct IdBlk
{
char *IdName;
struct IdBlk *IdNext;
struct IdBlk *AlphaLnk;
struct RfBlk *TopLnk;
struct RfBlk *LstLnk;
} IdBlk;
typedef struct HashBlk
{
struct IdBlk *IdFirst;
int IdCount;
} HashBlk;
typedef struct AlphaHdr
{
struct IdBlk *AlphaTop;
struct IdBlk *AlphaLst;
} AlphaHdr;
/********************************************************************/
/* */
/* function prototypes */
/* */
/********************************************************************/
void main(int PArgC,char **PArgV);
void ListErr(void);
void UseErr(int X);
int ProcFile(char *FileName,int IncNum);
void GetIncludeFileId(char *Token,FILE *InFile,int *SysSw);
void Echo(char Ch);
void InitOutput(void);
void EchoLine(void);
void CheckPage(void);
int GetToken(FILE *InFile ,char *Token,int *TokLen,
int *EofFlag);
int FileChar(FILE *InFile,int *Eof);
int RdChar(FILE *InFile,int *EofFlag,int EchoFlag);
int CheckToken(char *Token);
void PutToken(char *Token,int Ref);
void ChainAlpha(struct IdBlk *CaPtr,char *CaToken);
struct IdBlk *AllocId(char *Token);
struct RfBlk *AllocRf(int Ref);
struct RfBlk *AddRf(struct RfBlk *Ptr,int Ref);
void PrintTable(void);
void PrintHeader(void);
void NL(void);
/********************************************************************/
AlphaHdr AlphaVector[MAX_ALPHA];
HashBlk IdVector[MAX_WRD];
int PageNo; /* page number */
int PageLine; /* page line counter */
int LineNum; /* line number */
int EditNum; /* edit line number */
int IdCnt; /* number of unique identifiers */
int FileLevel; /* file level */
int Dummy; /* dummy integer */
int MaxCol = MAX_COL; /* maximum right column for listing line */
int Tab = TAB; /* standard tab expansion */
int PrtRef; /* on when printing XREF */
int CurChar; /* Current character pos in output buff */
int MaxChar; /* Maximum # chars is output buff */
char *LinePtr; /* Pointer to line buffer */
char ActFile[MAX_LEN];
char LstFile[MAX_LEN];
char GblFile[MAX_LEN];
char NameFile[MAX_LEN];
char PathName[MAX_LEN];
FILE *FLstFile;
int IsFlag; /* System file inclusion flag */
int IlFlag; /* Local file inclusion flag */
int LFlag; /* Listing only flag */
int OFlag; /* Output file flag */
int RFlag; /* XREF reserved words */
int FFlag; /* File list file flag */
int QFlag; /* Quiet mode flag */
int SFlag; /* Print hashing stats flag */
int CFlag; /* Current out buffer is a cont. */
/********************************************************************/
void main(int PArgC,char **PArgV)
{
char *Arg;
int ArgC;
char **ArgV;
int I;
FILE *NameIn;
ArgC = PArgC;
ArgV = PArgV;
if (ArgC < 2)
UseErr('f');
IsFlag = FALSE;
IlFlag = FALSE;
LFlag = FALSE;
OFlag = FALSE;
RFlag = FALSE;
FFlag = FALSE;
SFlag = FALSE;
QFlag = TRUE;
PathName[0] = '\0';
while (--ArgC != 0)
{
if (*(Arg = *++ArgV) == '-')
{
switch(tolower(*++Arg))
{
case 'i':
if (*++Arg == '\0')
{
IsFlag = !IsFlag;
IlFlag = !IlFlag;
}
else
do
{
switch(tolower(*Arg))
{
case 's':
IsFlag = !IsFlag;
break;
case 'l':
IlFlag = !IlFlag;
break;
case '\0':
break;
default:
UseErr('i');
}
} while (*++Arg != '\0');
break;
case 'l':
LFlag = !LFlag;
break;
case 'o':
OFlag = !OFlag;
strcpy(LstFile,++Arg);
if (LstFile[0] == '-')
UseErr('o');
break;
case 'r':
RFlag = !RFlag;;
break;
case 't':
I = atoi(++Arg);
if (I < MIN_TAB || I > MAX_TAB)
UseErr('t');
Tab = I;
break;
case 'w':
I = atoi(++Arg);
if (I <= MIN_COL || I >= 255)
UseErr('w');
MaxCol = I;
break;
case 'f':
FFlag = !FFlag;;
strcpy(NameFile,++Arg);
break;
case 'p':
strcpy(PathName,++Arg);
break;
case 's':
SFlag = !SFlag;
break;
case 'q':
QFlag = !QFlag;
break;
default:
UseErr('x');
}
}
}
if (OFlag)
{
if ((FLstFile = fopen(LstFile,"w")) == NULL)
{
printf("ERROR: Unable to create list file - %s\n",LstFile);
exit(1);
}
printf("XC: C XREF Utility v2.0\n\n");
}
for (LineNum = 0;LineNum < MAX_ALPHA;LineNum++)
{
AlphaVector[LineNum].AlphaTop = NULL;
AlphaVector[LineNum].AlphaLst = NULL;
}
for (LineNum = 0;LineNum < MAX_WRD;LineNum++)
{
IdVector[LineNum].IdFirst = NULL;
IdVector[LineNum].IdCount = 0;
}
InitOutput();
PrtRef = FALSE;
LineNum = 1;
FileLevel = 0;
PageLine = 0;
PageNo = 0;
EditNum = 1;
IdCnt = 0;
if (PathName[0] == '\0')
strcpy(PathName,"\\TURBOC\\INCLUDE\\");
ArgC = PArgC;
ArgC--;
ArgV = PArgV;
while (ArgC--)
{
strcpy(GblFile,*++ArgV);
if (*GblFile == '-')
continue;
ProcFile(GblFile,Dummy);
}
if (FFlag)
{
if ((NameIn = fopen(NameFile,"r")) == NULL)
{
printf("ERROR: Unable to open Names file - %s\n",NameFile);
exit(1);
}
while (fgets(GblFile,MAX_LEN,NameIn) != NULL)
{
GblFile[strlen(GblFile)- 1] = '\0'; /* remove trailing LF */
ProcFile(GblFile,Dummy);
}
fclose(NameIn);
}
if (!LFlag)
{
GblFile[0] = '\0';
PrintTable();
printf("\nUnique Symbols: %d\n",IdCnt);
}
if (OFlag)
{
NL();
fclose(FLstFile);
}
}
/********************************************************************/
void InitOutput(void)
{
MaxChar = MaxCol - START_COLUMN;
if ((LinePtr = calloc(1,MaxChar + 1)) == NULL)
{
printf("ERROR: Unable to allocate line buffer\n");
exit(1);
}
CurChar = 0;
CFlag = FALSE;
}
/********************************************************************/
void ListErr(void)
{
printf("\nERROR: Write error on list output file - %s\n", LstFile);
exit(1);
}
/********************************************************************/
void UseErr(int X)
{
printf("\nERROR: Invalid parameter specification. ");
if (X == 'f')
{
printf("No/invalid input file name specified.");
}
else
{
if (X == 'x')
{
printf("Switch not recognized.");
}
else
{
printf("Error in switch %c.",X);
}
}
printf("\n\nUsage: xc filename1 <filename2>... <flag(s)>\n\n");
printf("Flags: -i <s|l> = Enable file inclusion\n");
printf(" s = include system files\n");
printf(" l = include local files\n");
printf(" -l = Generate listing only\n");
printf(" -r = Cross-reference reserved words\n");
printf(" -o <outfile> = Write output to named file\n");
printf(" -t <tab width> = Number of spaces to expand tabs\n");
printf(" -w <width> = Width of output page\n");
printf(" -f <filename> = Name of file containing list\n");
printf(" -p <pathname> = Path to use for include files\n");
printf(" -s = Print hashing stats\n");
printf(" -q = Quiet mode\n\n");
printf("Flags -o, -t, -w, -f, and -p must be followed immediately by\n");
printf("value of the flag.\n\n");
printf("E.G. -w132\n\n");
exit(1);
}
/********************************************************************/
int ProcFile(char *FileName,int IncNum)
/* IncNum : prev. included line nmbr (return to caller) */
{
char Token[MAX_LEN]; /* token buffer */
int EofFlag; /* end-of-file indicator */
int TokLen; /* token length */
FILE *InFile; /* input file */
int SysSw; /* System include file indicator */
strcpy(ActFile,FileName);
EditNum = 1;
if ((InFile = fopen(FileName,"r")) == NULL)
{
printf("\nERROR: Unable to open input file: %s\n",FileName);
return(IncNum);
}
if (FileLevel++ == 0)
PrintHeader();
EofFlag = FALSE;
do
{
if (GetToken(InFile,Token,&TokLen,&EofFlag))
if (CheckToken(Token))
{
if (strcmp(Token,"#include") == 0)
{
GetIncludeFileId(Token,InFile,&SysSw);
if ((IsFlag && SysSw) || (IlFlag && !SysSw))
{
EditNum = ProcFile(Token,EditNum);
strcpy(ActFile,FileName);
}
continue;
}
PutToken(Token,LineNum);
}
} while (!EofFlag);
FileLevel -= 1;
fclose(InFile);
return(IncNum);
}
/********************************************************************/
void GetIncludeFileId(char *Token,FILE *InFile,int *SysSw)
{
char Ch;
char Term;
while ((((Term = getc(InFile)) == ' ') ||
(Term == '\t') ||
(Term == '\n')) &&
(Term != ERROR))
Echo(Term);
if (Term == ERROR)
{
printf("Error scanning #INCLUDE fileid(1): %c\n",Term);
exit(1);
}
Echo(Term);
*SysSw = (Term == '<');
if (*SysSw)
Term = '>'; /* terminator is > or " */
if ((!*SysSw) && (Term != '"'))
{
printf("Error scanning #INCLUDE fileid(2): %c\n",Term);
exit(1);
}
if (*SysSw)
{
strcpy(Token,PathName);
Token += strlen(PathName);
}
do
{
if ((Ch = getc(InFile)) != ' ')
{
*Token++ = Ch;
}
Echo(Ch);
} while ((Ch != Term) && Ch != ERROR);
if (Ch == ERROR)
{
printf("Error scanning #INCLUDE fileid(3): %c\n",Term);
exit(1);
}
*--Token = '\0';
while (((Term = getc(InFile)) != '\n') &&
(Term != ERROR))
Echo(Term);
Echo('\n');
}
/********************************************************************/
void Echo(char Ch)
{
if (Ch == '\t')
{
do
{
LinePtr[CurChar++] = ' ';
} while ((CurChar <= MaxChar) && ((CurChar % Tab) != 0));
CurChar--;
}
else if (Ch == '\n')
EchoLine();
else
LinePtr[CurChar++] = Ch;
if (CurChar == MaxChar)
{
EchoLine();
CFlag = TRUE;
}
}
/********************************************************************/
void EchoLine(void)
{
LinePtr[CurChar] = '\0';
CurChar = 0;
CheckPage();
if (CFlag)
{
CFlag = FALSE;
if (OFlag)
{
if (fprintf(FLstFile," %s\n",LinePtr) == ERROR)
ListErr();
}
else
printf(" %s\n",LinePtr) ;
}
else if (OFlag)
{
if (fprintf(FLstFile,"%4d %4d: %s\n",
LineNum++,EditNum++,LinePtr) == ERROR)
ListErr();
}
else
printf("%4d %4d: %s\n",LineNum++,EditNum++,LinePtr) ;
}
/********************************************************************/
void CheckPage(void)
{
if (++PageLine > LINES_PER_PAGE)
PrintHeader();
if (!PrtRef && OFlag && !QFlag)
if (LineNum % 60 == 1)
printf("\n<%4d> ",LineNum);
else
printf(".");
}
/********************************************************************/
/* */
/* 'getoken' returns the next valid identifier or */
/* reserved word from a given file along with the */
/* character length of the token and an end-of-file */
/* indicator */
/* */
/********************************************************************/
int GetToken(FILE *InFile,
char *Token,
int *TokLen,
int *EofFlag)
{
int C;
char *HToken;
char TempChar;
HToken = Token;
gtk:
*TokLen = 0;
Token = HToken;
/* */
/* Scan and discard any characters until an alphabetic or */
/* '_' (underscore) character is encountered or an end-of-file */
/* condition occurs */
/* */
while ((!isalpha(*Token = RdChar(InFile,EofFlag,FALSE))) &&
!*EofFlag &&
*Token != '_' &&
*Token != '0' &&
*Token != '#')
;
if (*EofFlag)
return(FALSE);
(*TokLen)++;
/* */
/* Scan and collect identified alpanumeric token until */
/* a non-alphanumeric character is encountered or and */
/* end-of-file condition occurs */
/* */
TempChar = '_';
while ((isalpha(C = RdChar(InFile,EofFlag,TRUE)) ||
isdigit(C) ||
C == '_' ||
C == TempChar) &&
!*EofFlag)
{
Echo(C);
if (*TokLen < MAX_LEN)
{
*++Token = C;
(*TokLen)++;
}
}
ungetc(C,InFile);
/* */
/* Check to see if a numeric hex or octal constant has */
/* been encountered ... if so dump it and try again */
/* */
if (*HToken == '0')
goto gtk;
/* */
/* Tack a NULL character onto the end of the token */
/* */
*++Token = '\0';
/* */
/* Screen out all #token strings except #include */
/* */
if (*HToken == '#' && strcmp(HToken,"#include"))
goto gtk;
return(TRUE);
}
/********************************************************************/
int FileChar(FILE *InFile,int *Eof)
{
int Char;
Char = getc(InFile);
if (Char == ERROR)
{
if (ferror(InFile))
{
printf("\nERROR: Error while processing input file - %s\n",ActFile);
exit(1);
}
else
{
*Eof = TRUE;
Char = 0;
}
}
return(Char);
}
/********************************************************************/
/* */
/* 'RdChar' returns the next valid character in a file */
/* and an end-of-file indicator. A valid character is */
/* defined as any which does not appear in either a */
/* commented or a quoted string ... 'RdChar' will correctly */
/* handle comment tokens which appear within a quoted */
/* string */
/* */
/********************************************************************/
int RdChar(FILE *InFile,int *EofFlag,int EchoFlag)
{
int C;
int QFlag; /* double quoted string flag */
int Q1Flag; /* single quoted string flag */
int CsFlag; /* comment start flag */
int CeFlag; /* comment end flag */
int CCnt; /* comment nesting level */
int TFlag; /* transparency flag */
/* EchoFlag tells whether or not the character is to echoed now */
/* or later. */
QFlag = FALSE;
Q1Flag = FALSE;
CsFlag = FALSE;
CeFlag = FALSE;
TFlag = FALSE;
CCnt = 0;
rch:
/* */
/* Fetch character from file */
/* */
C = FileChar(InFile,EofFlag);
if (*EofFlag)
return(C); /* EOF encountered */
if (EchoFlag)
return(C);
Echo(C);
if (TFlag)
{
TFlag = !TFlag;
goto rch;
}
if (C == '\\')
{
TFlag = TRUE;
goto rch;
}
/* */
/* If the character is not part of a quoted string check for and */
/* process commented strings. Nested comments are handled */
/* correctly but unbalanced comments are not. The assumption is */
/* made that the syntax of the program being xref'd is correct. */
/* */
if (!QFlag && !Q1Flag)
{
if (C == '*' && CCnt && !CsFlag)
{
CeFlag = TRUE;
goto rch;
}
if (C == '/' && CeFlag)
{
CCnt -= 1;
CeFlag = FALSE;
goto rch;
}
CeFlag = FALSE;
if (C == '/')
{
CsFlag = TRUE;
goto rch;
}
if (C == '*' && CsFlag)
{
CCnt += 1;
CsFlag = FALSE;
goto rch;
}
CsFlag = FALSE;
if (CCnt)
goto rch;
}
/* */
/* Check for and process quoted strings */
/* */
if ( C == '"' && !Q1Flag)
{
QFlag = !QFlag; /* toggle quote flag */
goto rch;
}
if (QFlag)
goto rch;
if (C == '\'')
{
Q1Flag = !Q1Flag; /* toggle quote flag */
goto rch;
}
if (Q1Flag)
goto rch;
/* */
/* Valid character ... return to caller */
/* */
return(C);
}
/********************************************************************/
int CheckToken(char *Token)
{
char UToken[MAX_LEN];
int I;
if (RFlag)
return(TRUE);
I = 0;
do
{
UToken[I] = toupper(Token[I]);
} while (Token[I++] != NULL);
switch(UToken[0])
{
case 'A':
if (strcmp(UToken,"ASM") == 0)
return(FALSE);
if (strcmp(UToken,"AUTO") == 0)
return(FALSE);
break;
case 'B':
if (strcmp(UToken,"BREAK") == 0)
return(FALSE);
break;
case 'C':
if (strcmp(UToken,"CHAR") == 0)
return (FALSE);
if (strcmp(UToken,"CDECL") == 0)
return (FALSE);
if (strcmp(UToken,"CONST") == 0)
return (FALSE);
if (strcmp(UToken,"CONTINUE") == 0)
return (FALSE);
if (strcmp(UToken,"CASE") == 0)
return (FALSE);
break;
case 'D':
if (strcmp(UToken,"DOUBLE") == 0)
return(FALSE);
if (strcmp(UToken,"DO") == 0)
return(FALSE);
if (strcmp(UToken,"DEFAULT") == 0)
return(FALSE);
break;
case 'E':
if (strcmp(UToken,"EXTERN") == 0)
return(FALSE);
if (strcmp(UToken,"ELSE") == 0)
return(FALSE);
if (strcmp(UToken,"ENUM") == 0)
return(FALSE);
break;
case 'F':
if (strcmp(UToken,"FLOAT") == 0)
return(FALSE);
if (strcmp(UToken,"FOR") == 0)
return(FALSE);
if (strcmp(UToken,"FAR") == 0)
return(FALSE);
break;
case 'G':
if (strcmp(UToken,"GOTO") == 0)
return(FALSE);
break;
case 'I':
if (strcmp(UToken,"INT") == 0)
return(FALSE);
if (strcmp(UToken,"IF") == 0)
return(FALSE);
if (strcmp(UToken,"INTERRUPT") == 0)
return(FALSE);
break;
case 'L':
if (strcmp(UToken,"LONG") == 0)
return(FALSE);
break;
case 'N':
if (strcmp(UToken,"NEAR") == 0)
return(FALSE);
break;
case 'P':
if (strcmp(UToken,"PASCAL") == 0)
return(FALSE);
break;
case 'R':
if (strcmp(UToken,"RETURN") == 0)
return(FALSE);
if (strcmp(UToken,"REGISTER") == 0)
return(FALSE);
break;
case 'S':
if (strcmp(UToken,"STRUCT") == 0)
return(FALSE);
if (strcmp(UToken,"SHORT") == 0)
return(FALSE);
if (strcmp(UToken,"STATIC") == 0)
return(FALSE);
if (strcmp(UToken,"SIZEOF") == 0)
return(FALSE);
if (strcmp(UToken,"SWITCH") == 0)
return(FALSE);
if (strcmp(UToken,"SIGNED") == 0)
return(FALSE);
break;
case 'T':
if (strcmp(UToken,"TYPEDEF") == 0)
return(FALSE);
break;
case 'U':
if (strcmp(UToken,"UNION") == 0)
return(FALSE);
if (strcmp(UToken,"UNSIGNED") == 0)
return(FALSE);
break;
case 'V':
if (strcmp(UToken,"VOID") == 0)
return(FALSE);
if (strcmp(UToken,"VOLATILE") == 0)
return(FALSE);
break;
case 'W':
if (strcmp(UToken,"WHILE") == 0)
return(FALSE);
break;
}
return(TRUE);
}
/********************************************************************/
/* */
/* Install parsed token and line reference in linked structure */
/* */
/********************************************************************/
void PutToken(char *Token,int Ref)
{
unsigned int HashIndex;
unsigned char *Ptr;
struct IdBlk *IdPtr;
struct HashBlk *HashPtr;
if (LFlag)
return;
/* Hashing algorithm is far from optimal but is adequate for a */
/* memory-bound index vector! */
HashIndex = 0;
for (Ptr = Token;*Ptr != '\0';Ptr++)
HashIndex = HashIndex*10 + *Ptr;
HashIndex = abs(HashIndex) % MAX_WRD;
HashPtr = &IdVector[HashIndex];
if ((IdPtr = HashPtr -> IdFirst) == NULL)
{
IdCnt++;
IdPtr = AllocId(Token);
HashPtr -> IdFirst = IdPtr;
HashPtr -> IdCount++;
ChainAlpha(IdPtr,Token);
IdPtr -> TopLnk = AllocRf(Ref);
IdPtr -> LstLnk = IdPtr -> TopLnk;
}
else
{
for (;IdPtr != NULL;IdPtr = IdPtr -> IdNext)
{
if (strcmp(IdPtr -> IdName,Token) == 0)
{
IdPtr -> LstLnk = AddRf(IdPtr -> LstLnk,Ref);
break;
}
}
if (IdPtr == NULL)
{
IdCnt++;
IdPtr = AllocId(Token);
IdPtr -> IdNext = HashPtr -> IdFirst;
HashPtr -> IdFirst = IdPtr;
HashPtr -> IdCount++;
ChainAlpha(IdPtr,Token);
IdPtr -> TopLnk = AllocRf(Ref);
IdPtr -> LstLnk = IdPtr -> TopLnk;
}
}
}
/********************************************************************/
void ChainAlpha(struct IdBlk *CaPtr,char *CaToken)
{
char C;
struct IdBlk *CurPtr;
struct IdBlk *LstPtr;
C = CaToken[0];
if (C == '_')
C = 0;
else if (isupper(C))
C = 1 + ((C - 'A')*2);
else
C = 2 + ((C - 'a')*2);
if (AlphaVector[C].AlphaTop == NULL)
{
AlphaVector[C].AlphaTop = CaPtr;
AlphaVector[C].AlphaLst = CaPtr;
CaPtr -> AlphaLnk = NULL;
return;
}
/* check to see if new IdBlk should be inserted between the */
/* AlphaVector header block and the first IdBlk in the current */
/* alpha chain */
if (strcmp(AlphaVector[C].AlphaTop -> IdName,CaToken) > 0)
{
CaPtr -> AlphaLnk = AlphaVector[C].AlphaTop;
AlphaVector[C].AlphaTop = CaPtr;
return;
}
if (strcmp(AlphaVector[C].AlphaLst -> IdName,CaToken) < 0)
{
AlphaVector[C].AlphaLst -> AlphaLnk = CaPtr;
CaPtr -> AlphaLnk = NULL;
AlphaVector[C].AlphaLst = CaPtr;
return;
}
CurPtr = AlphaVector[C].AlphaTop;
while (strcmp(CurPtr -> IdName,CaToken) < 0)
{
LstPtr = CurPtr;
CurPtr = LstPtr -> AlphaLnk;
}
LstPtr -> AlphaLnk = CaPtr;
CaPtr -> AlphaLnk = CurPtr;
return;
}
/********************************************************************/
struct IdBlk *AllocId(char *Token)
{
struct IdBlk *Ptr;
if ((Ptr = (struct IdBlk *)malloc(sizeof(IdBlk))) == NULL)
{
printf("\nERROR: Unable to allocate identifier block\n");
exit(1);
}
if ((Ptr -> IdName = malloc(strlen(Token) + 1)) == NULL)
{
printf("\nERROR: Unable to allocate identifier name block\n");
exit(1);
}
strcpy(Ptr -> IdName,Token);
Ptr -> AlphaLnk = NULL;
Ptr -> IdNext = NULL;
Ptr -> TopLnk = NULL;
Ptr -> LstLnk = NULL;
return (Ptr);
}
/********************************************************************/
struct RfBlk *AllocRf(int Ref)
{
int I;
struct RfBlk *Ptr;
if ((Ptr = (struct RfBlk *)malloc(sizeof(RfBlk))) == NULL)
{
printf("\nERROR: Unable to allocate reference block\n");
exit(1);
}
Ptr -> RefItem[0] = Ref;
Ptr -> RefCnt = 1;
Ptr -> Next = NULL;
for (I = 1;I < MAX_REF;I++)
Ptr -> RefItem[I] = 0;
return (Ptr);
}
/********************************************************************/
struct RfBlk *AddRf(struct RfBlk *Ptr,int Ref)
{
struct RfBlk *TempPtr;
TempPtr = Ptr;
if (Ptr -> RefCnt == MAX_REF)
{
TempPtr = AllocRf(Ref);
Ptr -> Next = TempPtr;
}
else
Ptr -> RefItem[Ptr -> RefCnt++] = Ref;
return (TempPtr);
}
/********************************************************************/
void PrintTable(void)
{
int Count;
int I;
int Ref;
int LineCount;
int RefsPerLine;
char SaveFirst;
struct IdBlk *IdPtr;
struct RfBlk *TbPtr;
struct HashBlk *HashPtr;
SaveFirst = NULL;
PrtRef = TRUE;
RefsPerLine = (MaxCol - 35) / 5;
PrintHeader();
for (I = 0;I < MAX_ALPHA;I++) /* for */
{
if ((IdPtr = AlphaVector[I].AlphaTop) != NULL) /* if 1 */
{
do /* do 1 */
{
if (SaveFirst != IdPtr -> IdName[0]) /* if 2 */
{
NL();
SaveFirst = IdPtr -> IdName[0];
} /* if 2 */
if (OFlag) /* if 3 */
{
if (fprintf(FLstFile,"%-33.32s: ",IdPtr -> IdName) == ERROR)
ListErr();
} /* if 3 */
else
printf("%-33.32s: ",IdPtr -> IdName);
TbPtr = IdPtr -> TopLnk;
LineCount = 0;
Count = 0;
do /* do 2 */
{
if (Count == MAX_REF) /* if 4 */
{
Count = 0;
TbPtr = TbPtr -> Next;
} /* if 4 */
if (TbPtr != NULL) /* if 5 */
{
if ((Ref = TbPtr -> RefItem[Count++]) != 0) /* if 6 */
{
if (OFlag)
{
if (fprintf(FLstFile,"%4d ",Ref) == ERROR)
ListErr();
}
else
printf("%4d ",Ref);
if (++LineCount == RefsPerLine)
{
NL();
if (OFlag)
{
if (fprintf(FLstFile,
" ") == ERROR)
ListErr();
}
else
printf(" ");
LineCount = 0;
}
} /* if 6 */
} /* if 5 */
else
Ref = 0;
} while (Ref); /* do 2 */
NL();
} while ((IdPtr = IdPtr -> AlphaLnk) != NULL); /* do 1 */
} /* if 1 */
} /* for */
NL();
if (SFlag)
{
PrintHeader();
Count = 0;
for (I = 0;I < MAX_WRD;I++)
{
HashPtr = &IdVector[I];
if (HashPtr -> IdCount != 0)
{
Count++;
CheckPage();
if (OFlag)
{
if (fprintf(FLstFile,"%5d %04X %5d %s\n",
Count,I,
HashPtr -> IdCount,
HashPtr -> IdFirst -> IdName) == ERROR)
ListErr();
}
else
printf("%5d %04X %5d %s\n",
Count,I,
HashPtr -> IdCount,
HashPtr -> IdFirst -> IdName);
}
}
}
}
/********************************************************************/
void PrintHeader(void)
{
int FileLen;
int CenterLen;
int NameStart;
int LeftLen;
int RightLen;
FileLen = strlen(GblFile);
CenterLen = MaxCol - 29 - FileLen;
if (CenterLen < 0)
{
NameStart = FileLen + CenterLen;
LeftLen = 0;
RightLen = 0;
}
else
{
NameStart = 0;
LeftLen = CenterLen >> 1;
RightLen = CenterLen - LeftLen;
}
if (OFlag)
{
if (fprintf(FLstFile,
"%cXC: C XREF Utility %*c%s%*c Page %4d\n\n",
FF,LeftLen,' ',&GblFile[NameStart],
RightLen,' ',++PageNo) == ERROR)
ListErr();
}
else
printf("%cXC: C XREF Utility %*c%s%*c Page %4d\n\n",
FF,LeftLen,' ',&GblFile[NameStart],
RightLen,' ',++PageNo);
PageLine = 2;
}
/********************************************************************/
void NL(void)
{
if (OFlag)
{
if (fprintf(FLstFile,"\n") == ERROR)
ListErr();
}
else
printf("\n");
CheckPage();
}